package library.http.progress;

import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.annotation.NonNull;

import java.io.IOException;
import java.lang.ref.WeakReference;

/**
 * Created by HKYS on 2016-9-6.
 */

public class ProgressPublisher {
    private static final long RATE_DEFAULT_PROGRESS = 100;
    private static final long RATE_DEFAULT_SPEED = 500;

    private final Handler handler;

    private final Object data;
    private final HttpProgressListener listener;

    private final long range;
    //进度回调接口
    private final long RATE_PROGRESS;
    private final long RATE_SPEED;

    private long startTime;
    private long lastTime = System.currentTimeMillis();
    private long progress;
    private long length;

    public ProgressPublisher(Object data, @NonNull HttpProgressListener progressListener, long range, long rateProgress, long rateSpeed) {
        this.data = data;
        this.listener = progressListener;
        this.range = range;
        this.RATE_PROGRESS = rateProgress > 0 ? rateProgress : RATE_DEFAULT_PROGRESS;
        this.RATE_SPEED = rateSpeed > 0 ? rateSpeed : RATE_DEFAULT_SPEED;

        this.handler = new InnerHandler(this, Looper.getMainLooper());
    }

    protected void flagStart() {
        progress = range;
        startTime = System.currentTimeMillis();
        lastTime = startTime;
    }

    protected void cancel() {
        if (handler != null)
            handler.removeCallbacksAndMessages(null);
    }

    protected void publishProgress(long progress, long length) throws IOException {
        if (Thread.interrupted()) {
            cancel();
            throw new IOException(new InterruptedException("线程已被中断"));
        }
        if (listener != null && handler != null) {
            long now = System.currentTimeMillis();
            if (progress == length || now - lastTime >= RATE_PROGRESS) {
                this.progress = range + progress;
                this.length = range + length;
                lastTime = now;
                if (handler.hasMessages(0))
                    handler.removeMessages(0);
                handler.sendEmptyMessage(0);
            }
        }
    }


    private static final class InnerHandler extends Handler {
        private final WeakReference<ProgressPublisher> reference;

        private long lastT;
        private long lastP;
        private float speed;

        public InnerHandler(final ProgressPublisher publisher, final Looper looper) {
            super(looper);
            this.reference = new WeakReference<>(publisher);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            ProgressPublisher publisher = reference.get();
            if (publisher == null || publisher.listener == null)
                return;
            if (lastT == 0)
                lastT = publisher.startTime;
            if (lastP == 0)
                lastP = publisher.range;
            switch (msg.what) {
                case 0:
                    long now = System.currentTimeMillis();
                    long offset = now - lastT;
                    if (speed == 0 || offset >= publisher.RATE_SPEED) {
                        speed = 1.0F * (publisher.progress - lastP) / (offset > 0 ? offset : 1);
                        lastP = publisher.progress;
                        lastT = now;
                    }
                    if (publisher.length != 0) {
                        float percent = 1.0F * publisher.progress / publisher.length;
                        publisher.listener.onProgress(publisher.data, publisher.progress, publisher.length, percent >= 0 ? percent : -1, speed);
                    }

                    if (speed > 0 && publisher.progress < publisher.length) {
                        sendEmptyMessageDelayed(0, publisher.RATE_SPEED * 2);
                    }
                    break;
            }
        }
    }


}
